/***********************************************************************
 *            Project: CoreCms
 *        ProjectName: 核心内容管理系统                                
 *                Web: https://www.corecms.net                      
 *             Author: 大灰灰                                          
 *              Email: jianweie@163.com                                
 *         CreateTime: 2021/1/31 21:45:10
 *        Description: 暂无
 ***********************************************************************/


using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using CoreCms.Net.Configuration;
using CoreCms.Net.DTO.ComponentsDTO;
using CoreCms.Net.IRepository;
using CoreCms.Net.IRepository.UnitOfWork;
using CoreCms.Net.IServices;
using CoreCms.Net.Loging;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.Entities.Expression;
using CoreCms.Net.Model.FromBody;
using CoreCms.Net.Model.ViewModels.Basics;
using CoreCms.Net.Model.ViewModels.DTO;
using CoreCms.Net.Model.ViewModels.UI;
using CoreCms.Net.Utility.Extensions;
using CoreCms.Net.Utility.Helper;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SqlSugar;
using static SKIT.FlurlHttpClient.Wechat.Api.Models.CgibinUserInfoBatchGetRequest.Types;


namespace CoreCms.Net.Services
{
    /// <summary>
    /// 商品表 接口实现
    /// </summary>
    public class CoreCmsGoodsServices : BaseServices<CoreCmsGoods>, ICoreCmsGoodsServices
    {
        private readonly ICoreCmsGoodsRepository _dal;
        private readonly IUnitOfWork _unitOfWork;
        private readonly ICoreCmsProductsServices _productsServices;
        private readonly ICoreCmsGoodsGradeServices _goodsGradeServices;
        private readonly ICoreCmsLabelServices _labelServices;
        private readonly ICoreCmsPromotionServices _promotionServices;
        private readonly ICoreCmsGoodsCollectionServices _goodsCollectionServices;
        private readonly ICoreCmsBrandServices _brandServices;
        private readonly ICoreCmsOrderItemServices _orderItemServices;
        private readonly ICoreCmsUserServices _userServices;
        private readonly ICoreCmsUserGradeServices _userGradeServices;

        private readonly IServiceProvider _serviceProvider;


        public CoreCmsGoodsServices(IUnitOfWork unitOfWork, ICoreCmsGoodsRepository dal
            , ICoreCmsProductsServices productsServices
            , ICoreCmsGoodsGradeServices goodsGradeServices
            , ICoreCmsLabelServices labelServices
            , ICoreCmsPromotionServices promotionServices
            , ICoreCmsGoodsCollectionServices goodsCollectionServices
            , ICoreCmsBrandServices brandServices
            , ICoreCmsOrderItemServices orderItemServices, ICoreCmsUserServices userServices, ICoreCmsUserGradeServices userGradeServices, IServiceProvider serviceProvider)
        {
            this._dal = dal;
            base.BaseDal = dal;
            _unitOfWork = unitOfWork;
            _productsServices = productsServices;
            _goodsGradeServices = goodsGradeServices;
            _labelServices = labelServices;
            _promotionServices = promotionServices;
            _goodsCollectionServices = goodsCollectionServices;
            _brandServices = brandServices;
            _orderItemServices = orderItemServices;
            _userServices = userServices;
            _userGradeServices = userGradeServices;
            _serviceProvider = serviceProvider;
        }


        /// <summary>
        /// 重写异步插入方法
        /// </summary>
        /// <param name="entity">实体数据</param>
        /// <returns></returns>
        public async Task<AdminUiCallBack> InsertAsync(FMGoodsInsertModel entity)
        {
            return await _dal.InsertAsync(entity);
        }

        /// <summary>
        /// 重写异步更新方法方法
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<AdminUiCallBack> UpdateAsync(FMGoodsInsertModel entity)
        {
            return await _dal.UpdateAsync(entity);
        }

        /// <summary>
        /// 重写删除指定ID集合的数据(批量删除)
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<AdminUiCallBack> DeleteByIdsAsync(int[] ids)
        {
            return await _dal.DeleteByIdsAsync(ids);
        }


        #region 批量修改价格==========================================
        /// <summary>
        /// 批量修改价格
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<AdminUiCallBack> DoBatchModifyPrice(FmBatchModifyPrice entity)
        {
            var jm = new AdminUiCallBack();

            var bl = false;
            //获取商品信息
            var goods = await base.BaseDal.QueryListByClauseAsync(p => entity.ids.Contains(p.id));
            if (!goods.Any())
            {
                jm.msg = GlobalConstVars.DataisNo;
                return jm;
            }
            var goodIds = goods.Select(p => p.id).ToList();
            //获取货品信息
            var products = await _productsServices.QueryListByClauseAsync(p => goodIds.Contains((int)p.goodsId));
            var productIds = products.Select(p => p.id).ToList();
            //获取自定义价格信息
            var goodsGrade = await _goodsGradeServices.QueryListByClauseAsync(p => goodIds.Contains(p.goodsId));
            var goodsGradeIds = goodsGrade.Select(p => p.id).ToList();

            var priceValue = entity.priceValue;

            switch (entity.modifyType)
            {
                case "=":
                    if (entity.priceType == GlobalEnumVars.PriceType.price.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { price = priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType == GlobalEnumVars.PriceType.costprice.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { costprice = priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType == GlobalEnumVars.PriceType.mktprice.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { mktprice = priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType.Contains("grade_price_"))
                    {
                        var gradeArr = entity.priceType.Split("_");
                        var goodsGradeId = Convert.ToInt16(gradeArr[2]);
                        if (goodsGradeId > 0)
                        {
                            bl = await _goodsGradeServices.UpdateAsync(p => new CoreCmsGoodsGrade { gradePrice = priceValue }, p => goodsGradeIds.Contains(p.id) && p.gradeId == goodsGradeId);
                        }
                    }
                    break;
                case "-":
                    if (entity.priceType == GlobalEnumVars.PriceType.price.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { price = p.price - priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType == GlobalEnumVars.PriceType.costprice.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { costprice = p.costprice - priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType == GlobalEnumVars.PriceType.mktprice.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { mktprice = p.mktprice - priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType.Contains("grade_price_"))
                    {
                        var gradeArr = entity.priceType.Split("_");
                        var goodsGradeId = Convert.ToInt16(gradeArr[2]);
                        if (goodsGradeId > 0)
                        {
                            bl = await _goodsGradeServices.UpdateAsync(p => new CoreCmsGoodsGrade { gradePrice = p.gradePrice - priceValue }, p => goodsGradeIds.Contains(p.id) && p.gradeId == goodsGradeId);
                        }
                    }
                    break;
                case "+":
                    if (entity.priceType == GlobalEnumVars.PriceType.price.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { price = p.price + priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType == GlobalEnumVars.PriceType.costprice.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { costprice = p.costprice + priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType == GlobalEnumVars.PriceType.mktprice.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { mktprice = p.mktprice + priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType.Contains("grade_price_"))
                    {
                        var gradeArr = entity.priceType.Split("_");
                        var goodsGradeId = Convert.ToInt16(gradeArr[2]);
                        if (goodsGradeId > 0)
                        {
                            bl = await _goodsGradeServices.UpdateAsync(p => new CoreCmsGoodsGrade { gradePrice = p.gradePrice + priceValue }, p => goodsGradeIds.Contains(p.id) && p.gradeId == goodsGradeId);
                        }
                    }
                    break;
                case "*":
                    if (entity.priceType == GlobalEnumVars.PriceType.price.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { price = p.price * priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType == GlobalEnumVars.PriceType.costprice.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { costprice = p.costprice * priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType == GlobalEnumVars.PriceType.mktprice.ToString())
                    {
                        bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { mktprice = p.mktprice * priceValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    }
                    else if (entity.priceType.Contains("grade_price_"))
                    {
                        var gradeArr = entity.priceType.Split("_");
                        var goodsGradeId = Convert.ToInt16(gradeArr[2]);
                        if (goodsGradeId > 0)
                        {
                            bl = await _goodsGradeServices.UpdateAsync(p => new CoreCmsGoodsGrade { gradePrice = p.gradePrice * priceValue }, p => goodsGradeIds.Contains(p.id) && p.gradeId == goodsGradeId);
                        }
                    }
                    break;
            }
            jm.code = bl ? 0 : 1;
            jm.msg = bl ? "价格修改成功" : "价格修改失败";

            return jm;
        }

        #endregion

        #region 批量修改库存==========================================
        /// <summary>
        /// 批量修改价格
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<AdminUiCallBack> DoBatchModifyStock(FmBatchModifyStock entity)
        {
            var jm = new AdminUiCallBack();

            var bl = false;
            //获取商品信息
            var goods = await base.BaseDal.QueryListByClauseAsync(p => entity.ids.Contains(p.id));
            if (!goods.Any())
            {
                jm.msg = GlobalConstVars.DataisNo;
                return jm;
            }
            var goodIds = goods.Select(p => p.id).ToList();

            var modifyValue = entity.modifyValue;

            switch (entity.modifyType)
            {
                case "=":
                    bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { stock = modifyValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    break;
                case "-":
                    bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { stock = p.stock - modifyValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    break;
                case "+":
                    bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { stock = p.stock + modifyValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    break;
                case "*":
                    bl = await _productsServices.UpdateAsync(p => new CoreCmsProducts() { stock = p.stock * modifyValue }, p => goodIds.Contains((int)p.goodsId) && p.isDel == false);
                    break;
            }
            jm.code = bl ? 0 : 1;
            jm.msg = bl ? "库存修改成功" : "库存修改失败";

            return jm;
        }

        #endregion

        #region 批量上架==========================================

        /// <summary>
        /// 批量上架
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<AdminUiCallBack> DoBatchMarketableUp(int[] ids)
        {
            var jm = new AdminUiCallBack();

            var bl = await _dal.UpdateAsync(p => new CoreCmsGoods() { isMarketable = true }, p => ids.Contains(p.id));
            jm.code = bl ? 0 : 1;
            jm.msg = bl ? "上架成功" : "上架失败";

            return jm;
        }
        #endregion

        #region 批量下架==========================================

        /// <summary>
        /// 批量下架
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<AdminUiCallBack> DoBatchMarketableDown(int[] ids)
        {
            var jm = new AdminUiCallBack();

            var bl = await _dal.UpdateAsync(p => new CoreCmsGoods() { isMarketable = false }, p => ids.Contains(p.id));
            jm.code = bl ? 0 : 1;
            jm.msg = bl ? "下架成功" : "下架失败";

            return jm;
        }
        #endregion

        #region 上架==========================================

        /// <summary>
        /// 上架
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<WebApiCallBack> DoMarketableUp(int ids)
        {
            var jm = new WebApiCallBack();

            var bl = await _dal.UpdateAsync(p => new CoreCmsGoods() { isMarketable = true }, p => ids == p.id);
            jm.code = bl ? 0 : 1;
            jm.msg = bl ? "上架成功" : "上架失败";
            jm.status = bl;

            return jm;
        }
        #endregion

        #region 下架==========================================

        /// <summary>
        /// 下架
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<WebApiCallBack> DoMarketableDown(int ids)
        {
            var jm = new WebApiCallBack();

            var bl = await _dal.UpdateAsync(p => new CoreCmsGoods() { isMarketable = false }, p => ids == p.id);
            jm.code = bl ? 0 : 1;
            jm.msg = bl ? "下架成功" : "下架失败";
            jm.status = bl;

            return jm;
        }
        #endregion

        #region 设置标签==========================================

        /// <summary>
        /// 设置标签
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<AdminUiCallBack> DoSetLabel(FmSetLabel entity)
        {
            var jm = new AdminUiCallBack();


            var names = entity.labels.Select(p => p.text).ToList();
            //获取已经存在数据库数据
            var olds = await _labelServices.QueryListByClauseAsync(p => names.Contains(p.name));
            if (olds.Any())
            {
                var oldNames = olds.Select(p => p.name).ToList();
                //获取未插入数据库数据
                var newNames = entity.labels.Where(p => !oldNames.Contains(p.text)).ToList();
                if (newNames.Any())
                {
                    var labels = new List<CoreCmsLabel>();
                    newNames.ForEach(p =>
                    {
                        labels.Add(new CoreCmsLabel()
                        {
                            name = p.text,
                            style = p.style
                        });
                    });
                    await _labelServices.InsertAsync(labels);
                }
            }
            else
            {
                var labels = new List<CoreCmsLabel>();
                entity.labels.ForEach(p =>
                {
                    labels.Add(new CoreCmsLabel()
                    {
                        name = p.text,
                        style = p.style
                    });
                });
                await _labelServices.InsertAsync(labels);
            }

            var items = await _labelServices.QueryListByClauseAsync(p => names.Contains(p.name));
            var idsInts = items.Select(p => p.id).ToArray();
            var ids = String.Join(",", idsInts);

            var bl = await base.BaseDal.UpdateAsync(p => new CoreCmsGoods() { labelIds = ids }, p => entity.ids.Contains(p.id));

            jm.code = bl ? 0 : 1;
            jm.msg = bl ? "设置成功" : "设置失败";

            return jm;
        }
        #endregion

        #region 取消标签==========================================

        /// <summary>
        /// 取消标签
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<AdminUiCallBack> DoDeleteLabel(FmSetLabel entity)
        {
            var jm = new AdminUiCallBack();

            var names = entity.labels.Select(p => p.text).ToList();
            //获取已经存在数据库数据
            var labels = await _labelServices.QueryListByClauseAsync(p => names.Contains(p.name));
            var labelIds = labels.Select(p => p.id).ToList();

            var goods = await base.QueryListByClauseAsync(p => entity.ids.Contains(p.id));
            goods.ForEach(p =>
            {
                if (!string.IsNullOrEmpty(p.labelIds))
                {
                    var ids = CommonHelper.StringToIntArray(p.labelIds);
                    var newIds = ids.Except(labelIds).ToList();
                    if (newIds.Any())
                    {
                        p.labelIds = String.Join(",", newIds);
                    }
                    else
                    {
                        p.labelIds = "";
                    }
                }
            });

            var bl = await base.UpdateAsync(goods);

            jm.code = bl ? 0 : 1;
            jm.msg = bl ? "设置成功" : "设置失败";


            return jm;
        }
        #endregion

        #region 判断商品是否参加团购或者秒杀

        public bool IsInGroup(int goodId, out CoreCmsPromotion promotionsModel, int promotionId = 0)
        {
            promotionsModel = new CoreCmsPromotion();
            if (goodId == 0)
            {
                return false;
            }

            var dt = DateTime.Now;
            var where = PredicateBuilder.True<CoreCmsPromotion>();
            where = where.And(p => p.isEnable == true);
            if (promotionId > 0)
            {
                where = where.And(p => p.id == promotionId);
            }
            where = where.And(p =>
                (p.type == (int)GlobalEnumVars.PromotionType.Group ||
                 p.type == (int)GlobalEnumVars.PromotionType.Seckill));
            where = where.And(p => p.startTime < dt || p.endTime > dt);
            where = where.And(p => p.isDel == false);

            var promotions = _promotionServices.QueryByClause(where);
            if (promotions == null) return false;

            try
            {
                if (string.IsNullOrEmpty(promotions.parameters)) return false;
                var obj = JsonConvert.DeserializeAnonymousType(promotions.parameters, new
                {
                    goodsId = "",
                    num = 0,
                });
                if (obj.goodsId.ObjectToInt(0) != goodId) return false;
                promotionsModel = promotions;
                return true;
            }
            catch
            {
                return false;
            }
        }
        #endregion

        #region 获取商品重量

        /// <summary>
        /// 获取商品重量
        /// </summary>
        /// <param name="productsId"></param>
        /// <returns></returns>
        public async Task<decimal> GetWeight(int productsId)
        {
            return await _dal.GetWeight(productsId);
        }
        #endregion

        #region 库存改变机制
        /// <summary>
        /// 库存改变机制。
        /// 库存机制：商品下单 总库存不变，冻结库存加1，
        /// 商品发货：冻结库存减1，总库存减1，
        /// 订单完成但未发货：总库存不变，冻结库存减1
        /// 商品退款&取消订单：总库存不变，冻结库存减1,
        /// 商品退货：总库存加1，冻结库存不变,
        /// 可销售库存：总库存-冻结库存
        /// </summary>
        /// <returns></returns>
        public WebApiCallBack ChangeStock(int productsId, string type = "order", int num = 0)
        {

            return _dal.ChangeStock(productsId, type, num);
        }
        #endregion


        #region 获取商品详情

        /// <summary>
        /// 获取商品详情
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userId"></param>
        /// <param name="isPromotion">是否涉及优惠</param>
        /// <param name="type"></param>
        /// <param name="groupId"></param>
        /// <param name="needSku">是否需要sku</param>
        /// <returns></returns>
        public async Task<CoreCmsGoods> GetGoodsDetail(int id, int userId = 0, bool isPromotion = false, string type = "goods", int groupId = 0, bool needSku = false)
        {
            var good = await _dal.QueryByClauseAsync(p => p.id == id, true);
            if (good == null) return null;
            //取图片集
            good.album = good.images.Split(",");
            //获取主图
            good.image = !string.IsNullOrEmpty(good.image) ? good.image : "/static/images/common/empty-banner.png";
            //获取用户信息
            if (userId > 0)
            {
                good.isFav = await _goodsCollectionServices.ExistsAsync(p => p.goodsId == good.id && p.userId == userId, true);
            }

            var product = new CoreCmsProducts();
            var products = new List<CoreCmsProducts>();
            if (needSku == true)
            {
                //取所有货品
                products = await _productsServices.QueryListByClauseAsync(p => p.goodsId == good.id && p.isDel == false, p => p.id, OrderByType.Asc, true);
                if (products == null) return null;
                //获取默认货品
                product = products.FirstOrDefault(p => p.isDefalut);
                if (product == null) return null;

                good.skuList = await GetCoreCmsProductsView(good, products, userId, isPromotion, type, groupId);
            }
            else
            {
                product = await _productsServices.QueryByClauseAsync(p => p.goodsId == good.id && p.isDel == false && p.isDefalut == true, true);
                if (product == null) return null;
            }

            //商品基础赋值===================================================================================================
            good.product = product;
            good.sn = product.sn;
            good.price = product.price;
            good.costprice = product.costprice;
            good.mktprice = product.mktprice;
            good.stock = product.stock;
            good.freezeStock = product.freezeStock;
            good.weight = product.weight;
            good.buyPinTuanCount = product.buyPinTuanCount;
            good.buyPromotionCount = product.buyPromotionCount;

            if (!string.IsNullOrEmpty(good.labelIds))
            {
                var ids = CommonHelper.StringToIntArray(good.labelIds);
                var lbs = await _labelServices.QueryAsync(true, true, 3600);
                good.labels = lbs.Where(p => ids.Contains(p.id)).ToList();
            }

            //获取商品最小价格
            good.minPrice = products.Any() ? products.OrderBy(p => p.price).First().price : product.price;
            //获取商品最大价格
            good.maxPrice = products.Any() ? products.OrderByDescending(p => p.price).First().price : product.price;

            //获取品牌
            good.brand = await _brandServices.QueryByIdAsync(good.brandId, true, true);

            //取出销量
            good.buyCount = good.initialSales + await _orderItemServices.GetSumAsync(p => p.goodsId == good.id, o => o.nums, true);
            return good;
        }
        #endregion

        #region 通过商品序列获取sku列表
        /// <summary>
        /// 通过商品序列获取sku列表
        /// </summary>
        /// <param name="good"></param>
        /// <param name="products"></param>
        /// <param name="userId"></param>
        /// <param name="isPromotion"></param>
        /// <param name="type"></param>
        /// <param name="groupId"></param>
        /// <returns></returns>
        public async Task<CoreCmsProductsView> GetCoreCmsProductsView(CoreCmsGoods good, List<CoreCmsProducts> products, int userId = 0, bool isPromotion = false, string type = "goods", int groupId = 0)
        {
            //获取默认货品
            var product = products.FirstOrDefault(p => p.isDefalut);
            if (product == null) return null;


            //获取会员级别优惠价
            //获取会员等级优惠价格体系
            decimal gradePrice = 0;
            if (userId > 0 && type == "goods")
            {
                //获取用户信息
                var userInfo = await _userServices.QueryByIdAsync(userId);
                if (userInfo != null)
                {
                    var goodsGrades = await _goodsGradeServices.QueryByClauseAsync(p => p.goodsId == good.id && p.gradeId == userInfo.grade);
                    if (goodsGrades != null)
                    {
                        gradePrice = goodsGrades.gradePrice;
                    }
                }
            }
            //sku优惠计算===================================================================================
            using var container = _serviceProvider.CreateScope();
            var orderServices = container.ServiceProvider.GetService<ICoreCmsOrderServices>();
            var pinTuanRuleServices = container.ServiceProvider.GetService<ICoreCmsPinTuanRuleServices>();
            var promotionServices = container.ServiceProvider.GetService<ICoreCmsPromotionServices>();
            var promotionConditionServices = container.ServiceProvider.GetService<ICoreCmsPromotionConditionServices>();
            var promotionResultServices = container.ServiceProvider.GetService<ICoreCmsPromotionResultServices>();

            if (isPromotion)
            {
                var dt = DateTime.Now;
                if (type == GlobalEnumVars.OrderType.Group.ToString().ToLowerInvariant() || type == GlobalEnumVars.OrderType.Seckill.ToString().ToLowerInvariant())
                {
                    //团购秒杀默认时间过期后，不可以下单
                    var key = false;
                    var promotionInfo = await promotionServices.QueryByClauseAsync(p => p.startTime < dt && p.endTime > dt && p.id == groupId, true);
                    if (promotionInfo != null)
                    {
                        //去除所有的条件
                        var promotionCondition = await promotionConditionServices.QueryByClauseAsync(p => p.promotionId == promotionInfo.id);
                        if (!string.IsNullOrEmpty(promotionCondition.parameters))
                        {
                            JObject parameters = (JObject)JsonConvert.DeserializeObject(promotionCondition.parameters);
                            if (parameters.ContainsKey("goodsId") && parameters.ContainsKey("nums"))
                            {
                                var objNums = Convert.ToInt32(parameters["nums"]);
                                var goodsIds = CommonHelper.StringToIntArray(parameters["goodsId"].ObjectToString());
                                key = goodsIds.Any() && goodsIds.Contains(good.id);
                            }
                        };
                    }
                    if (key)
                    {
                        //走到这一步就说明所有的促销条件都符合，那么就去计算结果
                        var promotionResult = await promotionResultServices.QueryByClauseAsync(p => p.promotionId == promotionInfo.id);
                        if (!string.IsNullOrEmpty(promotionResult.parameters))
                        {
                            foreach (var productModel in products)
                            {
                                var item = new CartProducts()
                                {
                                    id = 0,
                                    isSelect = true,
                                    userId = userId,
                                    productId = productModel.id,
                                    nums = 1,
                                    products = productModel
                                };
                                decimal promotionMoney;
                                JObject parameters = (JObject)JsonConvert.DeserializeObject(promotionResult.parameters);
                                switch (promotionResult.code)
                                {
                                    //指定商品减固定金额
                                    case "GOODS_REDUCE":
                                        promotionMoney = promotionResultServices.result_GOODS_REDUCE(parameters, item, promotionInfo);
                                        break;
                                    //指定商品打X折
                                    case "GOODS_DISCOUNT":
                                        promotionMoney = promotionResultServices.result_GOODS_DISCOUNT(parameters, item, promotionInfo);
                                        break;
                                    //指定商品一口价
                                    case "GOODS_ONE_PRICE":
                                        promotionMoney = promotionResultServices.result_GOODS_ONE_PRICE(parameters, item, promotionInfo);
                                        break;
                                    //指定商品每第几件减指定金额
                                    case "GOODS_HALF_PRICE": //todo 指定商品每第几件减指定金额
                                        promotionMoney = promotionResultServices.result_GOODS_HALF_PRICE(parameters, item, promotionInfo);
                                        break;
                                    default:
                                        promotionMoney = 0;
                                        break;
                                }
                                //productModel.price = Math.Round(productModel.price - promotionMoney, 2);
                            }
                        }
                    }

                }
                else
                {
                    //走全局优惠模式
                    var promotions = await promotionServices.QueryListByClauseAsync(p => p.isEnable == true && p.startTime < dt && p.endTime > dt && p.type == (int)GlobalEnumVars.PromotionType.Promotion && p.isDel == false, p => p.sort, OrderByType.Asc, true);

                }
            }

            //获取活动数量===================================================================================
            var stock = 0;
            var isMaxPinTuanGoodsNums = false;
            var buyPinTuanCount = 0;
            var isMaxGroupOrSeckillGoodsNums = false;
            var buyPromotionCount = 0;
            if (type == GlobalEnumVars.OrderType.PinTuan.ToString().ToLowerInvariant())
            {
                //把拼团的一些属性等加上
                var pinTuanRule = pinTuanRuleServices.QueryMuchFirst<CoreCmsPinTuanRule, CoreCmsPinTuanGoods, CoreCmsPinTuanRule>(
                    (role, pinTuanGoods) => new object[] { JoinType.Inner, role.id == pinTuanGoods.ruleId }
                    , (role, pinTuanGoods) => role
                    , (role, pinTuanGoods) => pinTuanGoods.goodsId == good.id);
                //调整前台显示数量
                var checkOrder = orderServices.FindLimitOrderByGoodId(good.id, userId, pinTuanRule.startTime, pinTuanRule.endTime, (int)GlobalEnumVars.OrderType.PinTuan);
                if (pinTuanRule.maxGoodsNums != 0 && pinTuanRule.maxNums != 0)
                {
                    isMaxPinTuanGoodsNums = true;
                    //总剩余可购买总数量
                    var residue = pinTuanRule.maxGoodsNums - checkOrder.TotalOrders;
                    //用户剩余可购买数量
                    var userResidue = pinTuanRule.maxGoodsNums - checkOrder.TotalUserOrders;
                    //求最小匹配
                    stock = userResidue > residue ? residue : userResidue;
                }
                else if (pinTuanRule.maxNums != 0 && pinTuanRule.maxNums == 0)
                {
                    //限制个人最多购买数量
                    stock = pinTuanRule.maxNums - checkOrder.TotalUserOrders == 0 ? 0 : pinTuanRule.maxNums - checkOrder.TotalUserOrders;
                }
                else if (pinTuanRule.maxNums == 0 && pinTuanRule.maxNums != 0)
                {
                    //限制最大购买总数
                    stock = pinTuanRule.maxGoodsNums - checkOrder.TotalOrders == 0 ? 0 : pinTuanRule.maxGoodsNums - checkOrder.TotalOrders;
                }
                buyPinTuanCount = checkOrder.TotalOrders;
            }
            else if (type == GlobalEnumVars.OrderType.Group.ToString().ToLowerInvariant() || type == GlobalEnumVars.OrderType.Seckill.ToString().ToLowerInvariant())
            {
                if (!IsInGroup(good.id, out var groupModel, groupId))
                {
                    return null;
                }
                var orderType = type == GlobalEnumVars.OrderType.Seckill.ToString().ToLowerInvariant()
                    ? (int)GlobalEnumVars.OrderType.Group
                    : (int)GlobalEnumVars.OrderType.Seckill;

                //调整前台显示数量
                var checkOrder = orderServices.FindLimitOrderByGoodId(good.id, userId, groupModel.startTime, groupModel.endTime, orderType);
                if (groupModel.maxGoodsNums != 0 && groupModel.maxNums != 0)
                {
                    isMaxGroupOrSeckillGoodsNums = true;
                    //总剩余可购买总数量
                    var residue = groupModel.maxGoodsNums - checkOrder.TotalOrders;
                    //用户剩余可购买数量
                    var userResidue = groupModel.maxGoodsNums - checkOrder.TotalUserOrders;
                    //求最小匹配
                    stock = userResidue > residue ? residue : userResidue;
                }
                else if (groupModel.maxNums != 0 && groupModel.maxNums == 0)
                {
                    isMaxGroupOrSeckillGoodsNums = true;
                    //限制个人最多购买数量
                    stock = groupModel.maxNums - checkOrder.TotalUserOrders;
                }
                else if (groupModel.maxNums == 0 && groupModel.maxNums != 0)
                {
                    isMaxGroupOrSeckillGoodsNums = true;
                    //限制最大购买总数
                    stock = groupModel.maxGoodsNums - checkOrder.TotalOrders;
                }
                buyPromotionCount = checkOrder.TotalOrders;
            }


            //sku前端json组合实体===================================================================================
            CoreCmsProductsView result;
            //如果是多规格商品，算多规格
            if (good.openSpec == 1 && !string.IsNullOrEmpty(good.spesDesc))
            {
                // 1910&&电线型号:1.5mm²|1911&&电线型号:2.5mm²|1912&&电线型号:4mm²|1913&&电线型号:6mm²|1901&&电线颜色:红色|1902&&电线颜色:蓝色|1903&&电线颜色:黄色|1904&&电线颜色:绿色|1905&&电线颜色:双色
                // 电线型号:1.5mm²,电线颜色:蓝色
                var defaultSpec = new Dictionary<string, List<string>>();
                foreach (var item in good.spesDesc.Split("|"))
                {
                    //1911&&电线型号:2.5mm²
                    var temp = item.Split("&&")[1].Split(":");
                    var name = temp[0];
                    var value = temp[1];
                    if (!defaultSpec.ContainsKey(name))
                    {
                        defaultSpec.Add(name, new List<string>());
                    }
                    defaultSpec[name].Add(value);
                }
                result = new CoreCmsProductsView();
                result._id = product.id.ToString();
                result.name = good.name;
                result.goods_thumb = product.images;
                result.buyPinTuanCount = buyPinTuanCount;
                result.buyPromotionCount = buyPromotionCount;

                var skuList = new List<Product_Sku_listItem>();
                products.ForEach(o =>
                {
                    var item = new Product_Sku_listItem();
                    item._id = o.id.ToString();
                    item.goods_id = good.id.ToString();
                    item.goods_name = good.name;
                    item.image = o.images;
                    item.price = o.price - gradePrice; //减去会员等级价格
                    item.sku_name_arr = o.spesDesc.Split(",").Select(s => s.Split(":")[1]).ToList();
                    item.stock = o.stock;
                    if (type == GlobalEnumVars.OrderType.PinTuan.ToString().ToLowerInvariant())
                    {
                        if (isMaxPinTuanGoodsNums)
                        {
                            item.stock = stock;
                        }
                    }
                    else if (type == GlobalEnumVars.OrderType.Group.ToString().ToLowerInvariant() || type == GlobalEnumVars.OrderType.Seckill.ToString().ToLowerInvariant())
                    {
                        if (isMaxGroupOrSeckillGoodsNums)
                        {
                            item.stock = stock;
                        }
                    }
                    skuList.Add(item);
                });

                result.sku_list = skuList;

                result.spec_list = defaultSpec.Select(d => new Product_Spec_listItem()
                {
                    name = d.Key,
                    list = d.Value.Select(s => new Product_Sku_list
                    {
                        name = s
                    }).ToList(),
                }).ToList();
            }
            else
            {
                result = new CoreCmsProductsView();
                result._id = product.id.ToString();
                result.name = good.name;
                result.goods_thumb = product.images;
                result.buyPinTuanCount = buyPinTuanCount;
                result.buyPromotionCount = buyPromotionCount;

                var skuList = new List<Product_Sku_listItem>();
                products.ForEach(o =>
                {
                    var item = new Product_Sku_listItem();
                    item._id = o.id.ToString();
                    item.goods_id = good.id.ToString();
                    item.goods_name = good.name;
                    item.image = o.images;
                    item.price = o.price - gradePrice; //减去会员等级价格
                    item.sku_name_arr = new List<string> { "默认" };
                    item.stock = o.stock;
                    if (type == GlobalEnumVars.OrderType.PinTuan.ToString().ToLowerInvariant())
                    {
                        if (isMaxPinTuanGoodsNums)
                        {
                            item.stock = stock;
                        }
                    }
                    else if (type == GlobalEnumVars.OrderType.Group.ToString().ToLowerInvariant() || type == GlobalEnumVars.OrderType.Seckill.ToString().ToLowerInvariant())
                    {
                        if (isMaxGroupOrSeckillGoodsNums)
                        {
                            item.stock = stock;
                        }
                    }

                    skuList.Add(item);
                });
                result.sku_list = skuList;
                result.spec_list = new List<Product_Spec_listItem>() {
                    new Product_Spec_listItem(){
                        list = new List<Product_Sku_list>{
                            new Product_Sku_list{
                                name =  "默认"
                            }
                        },
                        name = "默认"
                    }
                };
            }
            return result;
        }

        #endregion

        #region 获取随机推荐数据

        /// <summary>
        /// 获取随机推荐数据
        /// </summary>
        /// <param name="number"></param>
        /// <param name="isRecommend"></param>
        /// <returns></returns>
        public async Task<List<GoodListDTO>> GetGoodsRecommendList(int number, bool isRecommend = false)
        {
            return await _dal.GetGoodsRecommendList(number, isRecommend);
        }
        #endregion

        #region 获取数据总数
        /// <summary>
        ///     获取数据总数
        /// </summary>
        /// <param name="predicate">条件表达式树</param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <returns></returns>
        public async Task<int> GetCountAsync(Expression<Func<CoreCmsGoods, bool>> predicate, bool blUseNoLock = false)
        {
            return await _dal.GetCountAsync(predicate, blUseNoLock);
        }

        #endregion

        #region 重写根据条件查询分页数据
        /// <summary>
        ///     重写根据条件查询分页数据
        /// </summary>
        /// <param name="predicate">判断集合</param>
        /// <param name="orderByType">排序方式</param>
        /// <param name="pageIndex">当前页面索引</param>
        /// <param name="pageSize">分布大小</param>
        /// <param name="orderByExpression"></param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <returns></returns>
        public async Task<IPageList<CoreCmsGoods>> QueryPageAsync(Expression<Func<CoreCmsGoods, bool>> predicate,
            Expression<Func<CoreCmsGoods, object>> orderByExpression, OrderByType orderByType, int pageIndex = 1,
            int pageSize = 20, bool blUseNoLock = false)
        {
            return await _dal.QueryPageAsync(predicate, orderByExpression, orderByType, pageIndex, pageSize, blUseNoLock);
        }
        #endregion

        #region 重写根据条件查询一定数量数据
        /// <summary>
        ///     重写根据条件查询一定数量数据
        /// </summary>
        /// <param name="predicate">条件表达式树</param>
        /// <param name="take">获取数量</param>
        /// <param name="orderByPredicate">排序字段</param>
        /// <param name="orderByType">排序顺序</param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <returns></returns>
        public async Task<List<CoreCmsGoods>> QueryListByClauseAsync(Expression<Func<CoreCmsGoods, bool>> predicate, int take,
            Expression<Func<CoreCmsGoods, object>> orderByPredicate, OrderByType orderByType, bool blUseNoLock = false)
        {
            return await _dal.QueryListByClauseAsync(predicate, take, orderByPredicate, orderByType, blUseNoLock);
        }
        #endregion

        #region 重写根据条件查询数据
        /// <summary>
        ///     重写根据条件查询数据
        /// </summary>
        /// <param name="predicate">条件表达式树</param>
        /// <param name="orderBy">排序字段，如name asc,age desc</param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <returns>泛型实体集合</returns>
        public async Task<List<CoreCmsGoods>> QueryListByClauseAsync(Expression<Func<CoreCmsGoods, bool>> predicate, string orderBy = "",
            bool blUseNoLock = false)
        {
            return await _dal.QueryListByClauseAsync(predicate, orderBy, blUseNoLock);
        }
        #endregion

        #region 重写根据条件及自定义排序查询分页数据
        /// <summary>
        ///     重写根据条件及自定义排序查询分页数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBy"></param>
        /// <param name="pageIndex">当前页面索引</param>
        /// <param name="pageSize">分布大小</param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <returns></returns>
        public async Task<IPageList<CoreCmsGoods>> QueryPageAsync(Expression<Func<CoreCmsGoods, bool>> predicate, string orderBy = "",
            int pageIndex = 1, int pageSize = 20, bool blUseNoLock = false)
        {
            return await _dal.QueryPageAsync(predicate, orderBy, pageIndex, pageSize, blUseNoLock);
        }
        #endregion


        #region 重写根据条件及自定义排序查询分页数据（返回DTO）

        /// <summary>
        ///     重写根据条件及自定义排序查询分页数据（返回DTO）
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderByExpression">排序方式组合</param>
        /// <param name="pageIndex">当前页面索引</param>
        /// <param name="pageSize">分布大小</param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <returns></returns>
        public async Task<IPageList<GoodListDTO>> QueryPageByDTOAsync(Expression<Func<GoodListDTO, bool>> predicate, string orderByExpression, int pageIndex = 1, int pageSize = 20, bool blUseNoLock = false)
        {
            return await _dal.QueryPageByDTOAsync(predicate, orderByExpression, pageIndex, pageSize, blUseNoLock);
        }
        #endregion

        #region 重写根据条件及自定义排序查询分页数据（返回DTO）

        /// <summary>
        ///     重写根据条件及自定义排序查询分页数据（返回DTO）
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderByExpression">排序方式组合</param>
        /// <param name="pageIndex">当前页面索引</param>
        /// <param name="pageSize">分布大小</param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <returns></returns>
        public async Task<IPageList<GoodListDTO>> QueryPageByDTOAsyncTow(Expression<Func<GoodListDTO, bool>> predicate, string orderByExpression, int pageIndex = 1, int pageSize = 20, bool blUseNoLock = false)
        {
            return await _dal.QueryPageByDTOAsyncTow(predicate, orderByExpression, pageIndex, pageSize, blUseNoLock);
        }
        #endregion


        /// <summary>
        ///     根据条件查询代理池商品分页数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBy"></param>
        /// <param name="pageIndex">当前页面索引</param>
        /// <param name="pageSize">分布大小</param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <returns></returns>
        public async Task<IPageList<CoreCmsGoods>> QueryAgentGoodsPageAsync(Expression<Func<CoreCmsGoods, bool>> predicate,
            int pageIndex = 1, int pageSize = 20, bool blUseNoLock = false)
        {
            return await _dal.QueryAgentGoodsPageAsync(predicate, pageIndex, pageSize, blUseNoLock);
        }


        /// <summary>
        ///     根据条件查询商品及sku分页数据
        /// </summary>
        /// <param name="predicate">判断集合</param>
        /// <param name="orderByType">排序方式</param>
        /// <param name="pageIndex">当前页面索引</param>
        /// <param name="pageSize">分布大小</param>
        /// <param name="orderByExpression"></param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <returns></returns>
        public async Task<IPageList<CoreCmsGoods>> QueryGoodAndSkuPageAsync(Expression<Func<CoreCmsGoods, bool>> predicate,
            Expression<Func<CoreCmsGoods, object>> orderByExpression, OrderByType orderByType, int pageIndex = 1,
            int pageSize = 20, bool blUseNoLock = false)
        {
            return await _dal.QueryGoodAndSkuPageAsync(predicate, orderByExpression, orderByType, pageIndex, pageSize, blUseNoLock);
        }


        #region 获取下拉商品数据
        /// <summary>
        ///     获取下拉商品数据
        /// </summary>
        /// <returns></returns>
        public async Task<List<EnumEntity>> QueryEnumEntityAsync()
        {

            return await _dal.QueryEnumEntityAsync();
        }
        #endregion


        /// <summary>
        ///     获取商品及默认货品信息
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderByPredicate"></param>
        /// <param name="orderByType"></param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <returns></returns>
        public async Task<List<CoreCmsGoods>> QueryGoodWithDefaultProductAsync(Expression<Func<CoreCmsGoods, bool>> predicate,
            Expression<Func<CoreCmsGoods, object>> orderByPredicate, OrderByType orderByType, bool blUseNoLock = false)
        {
            return await _dal.QueryGoodWithDefaultProductAsync(predicate, orderByPredicate, orderByType, blUseNoLock);
        }

        /// <summary>
        ///     根据条件查询一定数量数据（用于组件）
        /// </summary>
        /// <param name="predicate">条件表达式树</param>
        /// <param name="take">获取数量</param>
        /// <param name="orderByPredicate">排序字段</param>
        /// <param name="orderByType">排序顺序</param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <param name="isDataCache">是否缓存</param>
        /// <param name="cacheTimes">缓存时间（分钟）</param>
        /// <returns></returns>
        public async Task<List<GoodListDTO>> QueryListByComponentsAsync(Expression<Func<GoodListDTO, bool>> predicate,
            int take,
            Expression<Func<GoodListDTO, object>> orderByPredicate, OrderByType orderByType, bool blUseNoLock = false,
            bool isDataCache = false, int cacheTimes = int.MaxValue)
        {
            return await _dal.QueryListByComponentsAsync(predicate, take, orderByPredicate, orderByType, blUseNoLock,
                isDataCache, cacheTimes);
        }


        /// <summary>
        ///     根据条件查询一定数量数据（用于组件）
        /// </summary>
        /// <param name="predicate">条件表达式树</param>
        /// <param name="take">获取数量</param>
        /// <param name="orderByPredicate">排序字段</param>
        /// <param name="orderByType">排序顺序</param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <param name="isDataCache">是否缓存</param>
        /// <param name="cacheTimes">缓存时间（分钟）</param>
        /// <returns></returns>
        public async Task<List<GoodListDTO>> QueryListByComponentsAsync(Expression<Func<GoodListDTO, bool>> predicate,
            int take, string orderByType = "", bool blUseNoLock = false,
            bool isDataCache = false, int cacheTimes = int.MaxValue)
        {
            return await _dal.QueryListByComponentsAsync(predicate, take, orderByType, blUseNoLock,
                isDataCache, cacheTimes);
        }


        /// <summary>
        ///     根据类型获取商品数据（用于PC，H5）
        /// </summary>
        /// <param name="predicate">条件表达式树</param>
        /// <param name="take">获取数量</param>
        /// <param name="orderByPredicate">排序字段</param>
        /// <param name="orderByType">排序顺序</param>
        /// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
        /// <param name="isDataCache">是否缓存</param>
        /// <param name="cacheTimes">缓存时间（分钟）</param>
        public async Task<List<GoodListDTO>> QueryListByTypeAsync(Expression<Func<GoodListDTO, bool>> predicate, int take, Expression<Func<GoodListDTO, object>> orderByPredicate, OrderByType orderByType,
            bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue)
        {
            return await _dal.QueryListByTypeAsync(predicate, take, orderByPredicate, orderByType, blUseNoLock, isDataCache, cacheTimes);
        }
    }
}
